<?php

class Rsj_EmbedIphoneIpadApp
{
    const CLASS_NAME = __CLASS__;
    const PLUGIN_KEY = 'embed_iphoneipad_app';
    const DB_OPTION_KEY = self::PLUGIN_KEY;
    const DISPLAY_NAME = 'Embed iPhone/iPad App';
    const PLUGIN_URL = 'http://wordpress.org/extend/plugins/embed-iphoneipad-app/';
    const FORUM_URL = 'http://wordpress.org/tags/embed-iphoneipad-app?forum_id=10';
    const BUG_TRACKER_URL = 'http://plugins.trac.wordpress.org/report';

	/**
     * @return true if switching to PHG Network affiliate happened
     */
    public static function isPhgEffective() {
		$now = new DateTime('now');
		$switchTime = new DateTime('2013-09-01 00:00:00');
		return ($now > $switchTime);
	}

    private static function dummyForI18nResource()
    {
        // Poedit can not pick up resource text in constant
        //   so these are needed to be somewhere in code
        __( 'Embed iPhone App' , self::PLUGIN_KEY );
        __( 'Embed iPhone/iPad App' , self::PLUGIN_KEY );
        __( 'Embed iPhone/iPad App Setting' , self::PLUGIN_KEY );
    }

    public static function formatPluginPage()
    {
        return '<a href="' . self::PLUGIN_URL . '" target="_blank">' . self::DISPLAY_NAME . '</a>';
    }

    protected $_locale = null;
    public function __construct()
    {
        $this->hook();
        $this->_locale = Rsj_LocaleFactory::create(get_locale());
    }

    public static function initializeI18n()
    {
        load_plugin_textdomain(
            self::PLUGIN_KEY,
            false,
            dirname(dirname(dirname( plugin_basename( __FILE__ ) ))) . '/languages/'
        );
    }

    public static function checkVersion()
    {
        if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
            require_once ABSPATH . '/wp-admin/includes/plugin.php';
            deactivate_plugins( __FILE__ );
            wp_die( self::getErrorMessage_NonSupportedPHP() );
        }

        global $wp_version;
        if ( version_compare( $wp_version, "3.3", "<" ) ) {
            require_once ABSPATH . '/wp-admin/includes/plugin.php';
            deactivate_plugins( __FILE__ );
            wp_die( self::getErrorMessage_NonSupportedWordPress() );
        }
    }

    public static function getErrorMessage_NonSupportedPHP()
    {
        return __( 'Embed iPhone/iPad App requires PHP5.3 or higher. The plugin has now disabled itself.' , self::PLUGIN_KEY );
    }

    public static function getErrorMessage_NonSupportedWordPress()
    {
        return __( 'Embed iPhone/iPad App requires WordPress3.3 or higher. The plugin has now disabled itself.' , self::PLUGIN_KEY );
    }

    const REGEX_APP_STORE = '#https?://itunes.apple.com/(?:(?P<country>\w{2})/)?app/(?P<slug>[\w\d-]*)?/?id(?P<id>[\d]{1,20})(?:\?mt=(?P<mt>[\d]{1,2}))?$#i';

    /**
     * set hooks on WordPress
     */
    public function hook()
    {
        add_action(
            'init',
            array( self::CLASS_NAME, 'initializeI18n' )
        );

        wp_embed_register_handler(
            self::PLUGIN_KEY . '_handler',
            self::REGEX_APP_STORE,
            array( &$this, 'convertAppUrl2ShortCode')
        );
        add_shortcode(
            self::PLUGIN_KEY,
            array( &$this, 'shortCode')
         );

        add_action(
            'wp_print_scripts',
            array( &$this, 'addStyleSheets')
        );
        add_action(
            'wp_print_scripts',
            array( &$this, 'addScripts')
        );

        if ( is_admin() ) {
            add_action(
                'admin_menu',
                array( &$this, 'registerMenu')
            );
            add_action(
                'admin_init',
                array( self::CLASS_NAME, 'checkVersion' )
            );
            add_action(
                'admin_init',
                array( &$this, 'registerSettings')
            );
        }
            add_filter(
                'plugin_action_links',
                array( &$this, 'registerSettingsLinkOnPluginsList'),
                10, // @priority default
                2   // @number_of_paramters
            );

        register_uninstall_hook(
            self::PLUGIN_KEY ,
            array( 'self', 'uninstall')
        );
    }

    // ------------------------------------------------------------------
    // -------------------------- callbacks -----------------------------
    // ------------------------------------------------------------------

    public function convertAppUrl2ShortCode( $matches, $attr, $url, $rawattr )
    {
        $media_type_param = '';
        extract( $matches );

        return '[' . self::PLUGIN_KEY . " id=\"{$id}\" country=\"{$country}\" slug=\"{$slug}\" mt=\"{$mt}\"]";
    }

    public function shortCode( $params )
    {
        // seeing 12 digits in 2012-08 but unknown how long it would be
        if ( !preg_match( "/^[\d]{1,20}$/", $params['id'] ) ) {
            return false;
        }
        $id = $params['id'];
        $country = $params['country'];
        //$slug = $params['slug'];
        //$mt = $params['mt'];
        $cleanUrl = Rsj_iTunes::getCleanUrl( $id, $country );

		$affiliateUrl = '';
        $errorMessage = null;
		if (self::isPhgEffective()) {
	        $phg = new Rsj_Phg();
            $affiliateUrl = $phg->getAffiliateUrl( $cleanUrl );
		} else {
			// use Linkshare affiliate
	        $linkshare = new Rsj_Linkshare();
	        try {
	            $affiliateUrl = $linkshare->getAffiliateUrl( $cleanUrl, $country );
	        } catch ( Rsj_EmbedIphoneIpadAppException $ex ) {
	            switch ( $ex->getCode() ) {
	                case 403:
	                    $affiliateUrl = $cleanUrl;
	                    $errorMessage = 'No affiliate token set for current country';
	                    break;
	                case 404:
	                    return $this->formatAppNotFound( $id, $ex );
	                case 500:
	                case 503:
	                default:
	                    $affiliateUrl = $cleanUrl;
	                    $errorMessage = 'Failed to generate affiliate link [ ' . $ex->getMessage() . ']';
	            }
	        }
		}
        $formattedPurchaseButton = $this->formatPurchaseButton( $affiliateUrl, $errorMessage );

        try {
            $appInfo = Rsj_iTunes::getAppInfo( $id, $country );
        } catch ( Rsj_EmbedIphoneIpadAppException $ex ) {
            return $this->formatAppNotFound( $id, $ex );
        }
        $formattedAppInfo = $this->formatAppInfo( $appInfo, $affiliateUrl, $errorMessage );

        $html = $formattedAppInfo . $formattedPurchaseButton . '</div></div>';

        return apply_filters( self::PLUGIN_KEY, $html );
    }

    public function addScripts()
    {
        wp_enqueue_script( 'jquery' );
    }

    public function addStyleSheets()
    {
        $myStyleUrl = plugins_url( 'css/' . self::PLUGIN_KEY . '.css', dirname(__DIR__) );
        $myStyleFile = plugin_dir_path(dirname(__DIR__)) . 'css/' . self::PLUGIN_KEY . '.css';
        if ( file_exists( $myStyleFile ) ) {
            wp_register_style( self::PLUGIN_KEY, $myStyleUrl );
            wp_enqueue_style( self::PLUGIN_KEY );
        }
    }

    public function registerMenu()
    {
        add_options_page(
            __( self::DISPLAY_NAME . ' Setting', self::PLUGIN_KEY ),
            __( 'Embed iPhone App', self::PLUGIN_KEY ),
            'administrator',
            self::PLUGIN_KEY,
            array( &$this, 'callbackRenderForm')
        );
    }

    public function registerSettings()
    {
        register_setting(
            self::PLUGIN_KEY,
            self::DB_OPTION_KEY,
            array( &$this, 'callbackValidate')
        );

        $this->registerSectionUsage();
//        $this->registerSectionTemplate();
        $this->registerSectionPhg();
        $this->registerSectionLinkshareUs();
        $this->registerSectionLinkshareJp();
        $this->registerSectionOtherCountries();
        $this->registerSectionOthers();
    }

    public function registerSettingsLinkOnPluginsList($links, $file)
    {
        if ($file === 'embed-iphoneipad-app/embed-iphoneipad-app.php') {
            $settings_link = '<a href="options-general.php?page=' . self::PLUGIN_KEY . '.php">Settings</a>'; 
            array_unshift($links, $settings_link);
        }
        return $links; 
    }

    public static function uninstall()
    {
        delete_option(self::DB_OPTION_KEY);
    }

    // ------------------------------------------------------------------
    // ---------------------- register sections -------------------------
    // ------------------------------------------------------------------

    protected function registerSectionUsage()
    {
        $sectionName = 'eia_usage';
        add_settings_section(
            $sectionName,
            __( 'Usage', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderUsage' ),
            self::PLUGIN_KEY
        );
    }

    protected function registerSectionTemplate()
    {
        $sectionName = 'eia_template';

        add_settings_section(
            $sectionName,
            __( 'Customize Look', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderCustomizeLookTitle' ),
            self::PLUGIN_KEY
        );

        add_settings_field(
            'eia_template',
            __( 'Customize Look template', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderCustomizeLookTemplate' ),
            self::PLUGIN_KEY,
            $sectionName
        );

    }

    protected function registerSectionPhg()
    {
        $sectionName = 'eia_phg';

        add_settings_section(
            $sectionName,
            __( 'PHG Network User Information', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderPhg' ),
            self::PLUGIN_KEY
        );

        add_settings_field(
            'eia_phg_token',
            __( 'PHG Network Affiliate Token', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderPhgToken' ),
            self::PLUGIN_KEY,
            $sectionName
        );

    }

    protected function registerSectionLinkshareUs()
    {
        $sectionName = 'eia_linkshare_us';

        add_settings_section(
            $sectionName,
            __( 'Linkshare(US) User Information', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderLinkshareUs' ),
            self::PLUGIN_KEY
        );

        add_settings_field(
            'eia_affiliate_us',
            __( 'Linkshare(US) Web Service Token', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderLinkshareUsToken' ),
            self::PLUGIN_KEY,
            $sectionName
        );

    }

    protected function registerSectionLinkshareJp()
    {
        $sectionName = 'eia_linkshare_jp';

        add_settings_section(
            $sectionName,
            __( 'Linkshare(Japan) User Information', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderLinkshareJp' ),
            self::PLUGIN_KEY
        );

        add_settings_field(
            'eia_affiliate_jp',
            __( 'Linkshare(Japan) Web Service Token', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderLinkshareJpToken' ),
            self::PLUGIN_KEY,
            $sectionName
        );
    }

    protected function registerSectionOtherCountries()
    {
        $sectionName = 'eia_other_countries';
        add_settings_section(
            $sectionName,
            __( 'Affiliate In Other Countries', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderOtherCountries' ),
            self::PLUGIN_KEY
        );
    }

    protected function registerSectionOthers()
    {
        $sectionName = 'eia_others';
        add_settings_section(
            $sectionName,
            __( 'Others', self::PLUGIN_KEY ),
            array( &$this, 'callbackRenderOthers' ),
            self::PLUGIN_KEY
        );
    }

    // ------------------------------------------------------------------
    // -------------------------- callbacks -----------------------------
    // ------------------------------------------------------------------

    public function callbackValidate( $input )
    {
        $this->validatePhgToken( $input );
        $this->validateLinkshareToken( $input, 'us' );
        $this->validateLinkshareToken( $input, 'jp' );
        $this->validateTemplate( $input );

        return $input;
    }

    public function validateTemplate( &$input )
    {
        $gottenValue = $input['template'];
        if ( is_null( $gottenValue ) || empty( $gottenValue ) ) {
            $input['template'] = <<<END_OF_TEMPLATE
<div style="text-align: left; font-size: 12px;">
<a style="padding: 5px 0 5px 0;
text-decoration: none;" href="%twitterlink%" title="Subscribe via Twitter" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/Twitter_alt.png" alt="Subscribe via Twitter" />
%twitter% Followers
</a><br />
<a style="padding: 5px 0 5px 0; text-decoration: none;" href="%facebooklink%" title="Subscribe via Facebook" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/facebook.png" alt="Subscribe via Facebook" />
%facebook% Fans
</a><br />
<a style="padding: 5px 0 5px 0; text-decoration: none;" href="%feedburnerlink%" title="Subscribe via RSS" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/rss.png" alt="Subscribe via RSS" />
%feedburner% Readers
</a><br />
<a style="padding: 5px 0 5px 0; text-decoration: none;" href="%youtubelink%" title="Subscribe to YouTube channel" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/youtube_alt.png" alt="Subscribe to YouTube channel" />
%youtube% Subscribers
</a><br />
<a style="padding: 5px 0 5px 0; text-decoration: none;" href="/wp-login.php" title="WordPress Members" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/Wordpress.png" alt="Subscribe to YouTube channel" />
%wordpress% Members
</a><br />
<a style="padding: 5px 0 5px 0; text-decoration: none;" href="%feedburneremail%" title="Subscribe via Email" target="_blank">
<img style="height:32px; vertical-align:middle; padding: 2px;" src="'.STCURL.'/isicons/mail.png" alt="Subscribe via eMail" />
Subscribe via eMail
</a>
</div>
END_OF_TEMPLATE;
            return;
        }
		return;
	}

    public function validatePhgToken( &$input )
    {
        $gottenValue = $input['phg']['at'];
        if ( is_null( $gottenValue ) || empty( $gottenValue ) ) {
            $input['phg']['at'] = '';

            return;
        }

        if ( preg_match( '/^[\w\d]{5,64}$/', $gottenValue ) !== 1 ) {
            add_settings_error(
                self::PLUGIN_KEY,
                'invalid_phg_token',
                __( 'The token seems not to be a valid PHG Network affiliate token. Please check your token on PHG Network', self::PLUGIN_KEY ),
                'error'
            );
            $input['phg']['at'] = '';

            return;
        }

        return;
    }

    public function validateLinkshareToken( &$input, $country )
    {
        $gottenValue = $input['affiliate'][$country];
        if ( is_null( $gottenValue ) || empty( $gottenValue ) ) {
            $input['affiliate'][$country] = '';

            return;
        }

        if ( preg_match( '/^[\w\d]{64}$/', $gottenValue ) !== 1 ) {
            add_settings_error(
                self::PLUGIN_KEY,
                'invalid_linkshare_token',
                sprintf(
                    __( 'The token seems not to be a valid Linkshare(%s) token. Please check your token on Linkshare', self::PLUGIN_KEY ),
                    $this->_locale->getDisplayLanguage( $country )
                ),
                'error'
            );
            $input['linkshare_' . $country . '_token'] = '';

            return;
        }

        return;
    }

    public function callbackRenderForm()
    {
        $unique_name = self::PLUGIN_KEY;
        $save_i18n = self::PLUGIN_KEY;

        echo '<div class="wrap">';
        echo '<div class="icon32" id="icon-options-general"></div>';
        echo '<h2>' . __( self::DISPLAY_NAME . ' Setting', self::PLUGIN_KEY ), '</h2>';
        echo '<div class="' . self::PLUGIN_KEY . '">';
        echo '<form action="options.php" method="post">';
        settings_fields( self::PLUGIN_KEY );
        do_settings_sections( self::PLUGIN_KEY );
        submit_button();
        echo '</form>';
        echo '</div>';
        echo '</div>';
    }

    public function callbackRenderUsage()
    {
        $admin_profile = get_admin_url() . 'profile.php';
        $admin_setting_media = get_admin_url() . 'options-media.php';
        $sampleAppUrl = 'http://itunes.apple.com/us/app/listtube/id487984113?mt=8';

        echo '<p>' . sprintf( __( '%s extracts iTunes App Store iOS application URL into a structured app info', self::PLUGIN_KEY ), self::DISPLAY_NAME ) . '</p>';
        echo '<h4>' . __( 'Example', self::PLUGIN_KEY ) . '</h4>';
        echo '<p>' . __( 'You just paste an URL of the app into the body. For example,', self::PLUGIN_KEY ) . '</p>';
        echo '<blockquote><code>' . sprintf( __( '%s', self::PLUGIN_KEY ), $sampleAppUrl ) . '</blockquote></code>';
        echo '<h4>' . __( 'Tips', self::PLUGIN_KEY ) . '</h4><ul>';
        echo '<li>' . sprintf( __( 'If you are not using HTML Editor but Visual Editor, you need to unlink the URL. <a href="%s">Check here</a>', self::PLUGIN_KEY ), $admin_profile ) . '</li>';
        global $wp_version;
        if ( version_compare( $wp_version, "3.5", "<" ) ) {
            echo '<li>' . sprintf( __( 'You may need to turn on URL embed settings in <a href="%s">[Settings]-[Media]</a>. You may also set <a href="%s">Maximum embed size width</a> to limit the maximum width of screenshots frame.', self::PLUGIN_KEY ), $admin_setting_media, $admin_setting_media ) . '</li>';
        } else {
            echo '<li>' . __( 'From WordPress 3.5, you can not customize maximum embed sizes. <a href="http://www.wpbeginner.com/wp-themes/how-to-set-oembed-max-width-in-wordpress-3-5-with-content_width/">Check here</a> if you make it back manually.', self::PLUGIN_KEY ) . '</li>';
        }
        echo '<li>' . sprintf( __( 'The app information are cached on database to avoid fetching data every time the post displayed. If you use any of <a href="%s" target="_blank">Object Cache plugins</a>, this plugin will use it and rendering will be much faster (recommended as it speeds up whole your WordPress).', self::PLUGIN_KEY ), 'http://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Cache_Plugins' ) . '</li>';
        echo '<li>' . sprintf( __( 'If affiliate tokens are not set, plugin\'s own tokens will be used for supporting further development.', self::PLUGIN_KEY ), 'http://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Cache_Plugins' ) . '</li>';

        echo '</ul>';
    }

    public function callbackRenderCustomizeLookTitle()
    {
        echo '<p>' . __( 'You may customize how the app info look', self::PLUGIN_KEY ) . '</p>';
    }

    public function callbackRenderCustomizeLookTemplate()
    {
        $options = get_option(self::DB_OPTION_KEY);
        $template = '';
        if (array_key_exists('template', $options)) {
            $template = $options['template'];
        }
        echo '<textarea name="' . self::DB_OPTION_KEY . '[template]"' . ' id="eia_customize_template" type="text"' . ' cols="80" rows="40" size="1000" maxlength="1000"' . '>' . $template . '</textarea>' . '<br />' . __( 'You may use the following tags:', self::PLUGIN_KEY ) . '<br />' . __( '%title%, %vendor%, %price%', self::PLUGIN_KEY );
    }

    public function callbackRenderPhg()
    {
        echo '<p>' . __( 'PHG Network user can convert App Store link to affiliate link', self::PLUGIN_KEY ) . '</p>';
    }

    public function callbackRenderPhgToken()
    {
        $options = get_option(self::DB_OPTION_KEY);
        $phg_at = '';
        if (array_key_exists('phg', $options)) {
            if (array_key_exists('at', $options['phg'])) {
                $phg_at = $options['phg']['at'];
            }
        }
        echo '<input name="' . self::DB_OPTION_KEY . '[phg][at]"' . ' id="eia_phg" type="text"' . ' size="64" maxlength="64"' . ' value="' . $phg_at . '" />' . '<br />' . __( 'PHG Network affiliate user <a href="http://affiliate.itunes.apple.com/signin">can get the key here</a>', self::PLUGIN_KEY ) . '<br />' . __( 'You can <a href="http://affiliate.itunes.apple.com/apply">register PHG Network</a> to earn commissions when the apps are sold', self::PLUGIN_KEY );
    }

    public function callbackRenderLinkshareUs()
    {
        echo '<p>' . __( '(Switched to PHG Network affiliate after October 1, 2013)', self::PLUGIN_KEY ) . '</p>';
        echo '<p>' . __( 'Linkshare user can convert App Store link to affiliate link', self::PLUGIN_KEY ) . '</p>';
    }

    public function callbackRenderLinkshareUsToken()
    {
        $options = get_option(self::DB_OPTION_KEY);
        echo '<input name="' . self::DB_OPTION_KEY . '[affiliate][us]"' . ' id="eia_affiliate_us" type="text"' . ' size="64" maxlength="64"' . ' value="' . $options['affiliate']['us'] . '" />' . '<br />' . __( 'Linkshare registered user <a href="http://cli.linksynergy.com/cli/publisher/links/webServices.php">can get the key here</a>', self::PLUGIN_KEY ) . '<br />' . __( 'You can <a href="http://ad.linksynergy.com/fs-bin/show?id=dLarP1p5PAY&bids=7097&type=3&subid=0">register Linkshare</a> to earn commissions when the apps are sold', self::PLUGIN_KEY );
    }

    public function callbackRenderLinkshareJp()
    {
        echo '<p>' . __( '(Switched to PHG Network affiliate after October 1, 2013)', self::PLUGIN_KEY ) . '</p>';
        echo '<p>' . __( 'Linkshare Japan user can convert App Store link to affiliate link', self::PLUGIN_KEY ) . '</p>';
    }

    public function callbackRenderLinkshareJpToken()
    {
        $options = get_option(self::DB_OPTION_KEY);
        echo '<input name="' . self::DB_OPTION_KEY . '[affiliate][jp]"' . ' id="eia_affiliate_jp" type="text"' . ' size="64" maxlength="64"' . ' value="' . $options['affiliate']['jp'] . '" />' . '<br />' . __( 'Linkshare Japan registered user <a href="http://cli.linksynergy.com/cli/publisher/links/webServices.php">can get the key here</a>', self::PLUGIN_KEY ) . '<br />' . __( 'You can <a href="http://click.linksynergy.com/fs-bin/click?id=RGWPXSqy5PM&offerid=78559.10000049&type=3&subid=0">register Linkshare Japan</a> to earn commissions when the apps are sold', self::PLUGIN_KEY );
    }

    public function callbackRenderOtherCountries()
    {
        echo '<p>' . sprintf( __( 'Currently this plugin does not support other affiliate providers in other countries/regions(Tradedoubler). We were not approved by them so unable to test.', self::PLUGIN_KEY ) ) . '</p>';
    }

    public function callbackRenderOthers()
    {
        $this->callbackRenderOthersEnvironment();
        $this->callbackRenderOthersFeedbacks();
        $this->callbackRenderOthersPaypal();
    }

    public function callbackRenderOthersEnvironment()
    {
        echo '<h4>' . __( 'Environment Check', self::PLUGIN_KEY ) . '</h4>';
        if ( extension_loaded('intl')) {
            echo '<p>' . __( 'php_intl extension is enabled, so countries, languages and currencies are displayed in your WordPress locale.', self::PLUGIN_KEY ) . '</p>';
        } else {
            echo '<p>' . __( 'Countries, languages and currencies are not properly localized. If you want better localization, please turn on php_intl extension.', self::PLUGIN_KEY ) . '</p>';
        }
    }

    public function callbackRenderOthersFeedbacks()
    {
        $plugin = __( 'Plugin Page' , self::PLUGIN_KEY );
        $forum = __( 'WordPress Plugin Forum' , self::PLUGIN_KEY );
        $bugTracker = __( 'WordPress Plugin Bug Tracker' , self::PLUGIN_KEY );
        echo '<h4>' . __( 'Feedbacks', self::PLUGIN_KEY ) . '</h4>';
        echo '<p>' . sprintf( __( 'If you like this plugin and keep using, please review it on <a href="%s" title="%s" target="_blank">%s</a>.', self::PLUGIN_KEY ), self::PLUGIN_URL, $plugin, $plugin ) . '</p>';
        echo '<p>' . sprintf( __( 'Questions should be asked on <a href="%s" title="%s" target="_blank">%s</a>.', self::PLUGIN_KEY ), self::FORUM_URL, $forum, $forum ) . '</p>';
        echo '<p>' . sprintf( __( 'If you find a bug, please file it on <a href="%s" title="%s" target="_blank">%s</a>.', self::PLUGIN_KEY ), self::BUG_TRACKER_URL, $bugTracker, $bugTracker ) . '</p>';
        echo '<p>' . sprintf( __( 'English correction and new language translation are <a href="%s" title="%s" target="_blank">welcome</a>.', self::PLUGIN_KEY ), self::BUG_TRACKER_URL, $bugTracker, $bugTracker ) . '</p>';
    }

    public function callbackRenderOthersPaypal()
    {
        $paypal = 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WRQATSNKVABZA';
        $title = 'Donate on Paypal';
        echo '<h4>' . __( 'Donation', self::PLUGIN_KEY ) . '</h4>';
        echo '<p>' . sprintf( __( 'Please support %s with a <a href="%s" title="%s" target="_blank">PayPal Donation</a>.', self::PLUGIN_KEY ), self::DISPLAY_NAME, $paypal, $title ) . '</p>';
    }

    // ------------------------------------------------------------------
    // -------------------------- formatter -----------------------------
    // ------------------------------------------------------------------

    protected function formatAppNotFound( $id, $ex )
    {
        $html = '<div class="eia_top">';
        $html .= '<div class="eia_error">';
        $html .= sprintf( __( "[app id:%d] %s %s", self::PLUGIN_KEY ), $id, $ex->getMessage(), self::formatPluginPage() );
        $html .= '</div>';
        $html .= '</div>';

        return $html;
    }

    protected function getArtworkVariationBy($url, $size = '150x150-75.png')
    {
		$result = preg_replace('/(png)$/', $size, $url);
		return !is_null($result)?$result:$url;
    }

    /**
     *
     * 
     * 
     */
    public function formatAppInfo( $appInfo, $affiliateUrl = null, $errorMessage = null )
    {
        $html = '<div class="eia_top">';
        $html .= '<h3 class="eia_title">' . $appInfo['trackName'] . '</h3>';
        $html .= '<a class="eia_icon" href="' . $affiliateUrl . '">';
        $html .= '<img src="' . $this->getArtworkVariationBy($appInfo['artworkUrl512']) . '"';
        // most RSS readers ignore external style sheets. To avoid non-styled
        // images, insert style only when called for feed.
        if (is_feed()) {
            $html .= ' width="150"';
        }
        $html .= ' />';
        $html .= '</a>';

        // genres
        $genres = $appInfo['genres'];
        /*
          // emphasize primary genre
          // primaryGenreName is not localized so we need dictionary to do this
          $primaryGenreName = $appInfo['primaryGenreName'];
          $otherGenres = array_diff($genres, array($primaryGenreName));
          $html .= '<div>' . __('Genre', self::PLUGIN_KEY) . ': ';
          $html .= '<span class="primary_genre">' . __($primaryGenreName) . '</span>';
          if (!empty($otherGenres)) {
          foreach ($otherGenres as $genre) {
          $html .= ', ' . $genre;
          }
          }
          $html .= '</div>';
         */
        $html .= '<div>' . __( 'Genre', self::PLUGIN_KEY ) . ': ';
        $html .= implode( ', ', $genres );
        $html .= '</div>';

        // languages
        $languageCodesISO2A = $appInfo['languageCodesISO2A'];
        $formattedLanguageNames = array( );
        foreach ($languageCodesISO2A as $languageCode) {
            $formattedLanguageNames[] = $this->_locale->getDisplayLanguage( $languageCode );
        }
        $html .= '<div>' . __( 'Language', self::PLUGIN_KEY ) . ': ';
        $html .= implode( ', ', $formattedLanguageNames );
        $html .= '</div>';

        // suppress device when RSS, because new versions makes the post
		// updated on feed too much.
        if (!is_feed()) {
	        // devices
	        $supportedDevices = $appInfo['supportedDevices'];
	        $html .= '<div>' . __( 'Devices', self::PLUGIN_KEY ) . ': ';
	        if ( count( $supportedDevices ) === 1 && $supportedDevices[0] === 'all' ) {
	            $html .= __( 'all', self::PLUGIN_KEY );
	        } else {
	            $html .= implode( ', ', $supportedDevices );
	        }
	        $html .= '</div>';
		}
        $html .= '<div>' . __( 'Price', self::PLUGIN_KEY ) . ': ';
        $price = $appInfo['price'];
        if ($price == 0) {
            $html .= __( 'free', self::PLUGIN_KEY );
        } else {
            $html .= $this->_locale->formatCurrency( $price, $appInfo['currency'] );
        }
        $html .= '</div>';

        $html .= '<div class="info_pack">';
        $html .= '<div>' . __( 'Version', self::PLUGIN_KEY ) . ': ';
        $html .= $appInfo['version'];
/* tentatively removed size info
        $html .= '&nbsp;' . __( 'Size', self::PLUGIN_KEY ) . ': ';
        $html .= '(' . $this->_locale->format( round( $appInfo['fileSizeBytes'] / 1024 / 1024, 2 ) ) . ' MB)';
*/
        $html .= '</div>';
        $html .= '</div><br />';

        $html .= '<div>' . __( 'Artist', self::PLUGIN_KEY ) . ': ';
        $html .= $appInfo['artistName'] . '</div>';
//        $html .= '<div>' . __( 'Seller', self::PLUGIN_KEY ) . ': ';
//        $html .= $appInfo['sellerName'] . '</div>';

        $releaseDate = date_i18n( get_option( 'date_format' ), strtotime( $appInfo['releaseDate'] ) );
        $html .= '<div>' . __( 'Released at', self::PLUGIN_KEY ) . ': ';
        $html .= $releaseDate . '</div>';

        // suppress rating when RSS, because ratings are frequently changed
        // and that makes the post updated on feed too much.
        if (!is_feed()) {
            // CSS only half star by TheBroth.com
            //   http://www.thebroth.com/blog/119/css-rating-stars
            $html .= '<div class="info_pack">';
            if ( array_key_exists( 'averageUserRating', $appInfo ) ) {
                $html .= '<div>' . __( 'User Rating (all version)', self::PLUGIN_KEY ) . ': </div>';
                $html .= $this->formatStar( (float) ($appInfo['averageUserRating']) );
                $html .= '<div>';
                $html .= '(' . sprintf( __( 'by %d', self::PLUGIN_KEY ), $appInfo['userRatingCount'] ) . ')';

                $html .= '</div>';
            } else {
                $html .= '<div>' . __( 'User Rating (all version)', self::PLUGIN_KEY ) . ': ';
                $html .= __( 'no rating yet', self::PLUGIN_KEY ) . '</div>';
            }
            $html .= '</div><!-- info_pack -->';

            $html .= '<div class="info_pack">';
            if ( array_key_exists( 'averageUserRatingForCurrentVersion', $appInfo ) ) {
                $html .= '<div>' . __( 'User Rating (current version)', self::PLUGIN_KEY ) . ': </div>';
                $html .= $this->formatStar( (float) ($appInfo['averageUserRatingForCurrentVersion']) );
                $html .= '<div>';
                $html .= '(' . sprintf( __( 'by %d', self::PLUGIN_KEY ), $appInfo['userRatingCountForCurrentVersion'] ) . ')';
                $html .= '</div>';
            } else {
                $html .= '<div>' . __( 'User Rating (current version)', self::PLUGIN_KEY ) . ': ';
                $html .= __( 'no rating yet', self::PLUGIN_KEY ) . '</div>';
            }
            $html .= '</div><!-- info_pack -->';
        }
        $html .= '<br /><div class="reset"/>';

        $embed_size_w = get_option( 'embed_size_w' );
        $style_to_override = '';
        if ($embed_size_w > 0) {
            $style_to_override = ' style="width: ' . $embed_size_w . 'px"';
        }
        $html .= '<h3 class="eia_screenshot_title">' . __( 'Screenshots', self::PLUGIN_KEY ) . '</h3>';
        $html .= '<div class="eia_screenshots_frame"';
        $html .= $style_to_override . '>';
        $html .= '<div class="eia_screenshots">';
        if ( array_key_exists( 'screenshotUrls', $appInfo ) && (count( $appInfo['screenshotUrls'] ) > 0) ) {
            foreach ($appInfo['screenshotUrls'] as $index => $imageUrl) {
                $html .= '<img src="' . $imageUrl . '"';
                $html .= ' alt="screenshot ' . $index . '"';
                $html .= ' class="eia_screenshot"';
                if (is_feed()) {
                    $html .= ' width="200"';
                }
                $html .= ' />';
            }
        }
        if ( array_key_exists( 'ipadScreenshotUrls', $appInfo ) && (count( $appInfo['ipadScreenshotUrls'] ) > 0) ) {
            foreach ($appInfo['ipadScreenshotUrls'] as $index => $imageUrl) {
                $html .= '<img src="' . $imageUrl . '"';
                $html .= ' alt="screenshot ' . $index . '"';
                $html .= ' class="eia_screenshot"';
                if (is_feed()) {
                    $html .= ' width="200"';
                }
                $html .= ' />';
            }
        }
        $html .= '<div class="reset"/>';
        $html .= '</div></div></div>';

        return $html;
    }

	protected function renderTemplate($template, $appInfo) {
	    $text = str_replace( '%name%', $appInfo['name'], $template );
	    return $text;
	}

    protected function formatStar( $rate )
    {
        $ratio = $rate * 20;
        $html = <<<END_OF_STAR
<div class="eia_rating_bar">
  <div style="width:${ratio}%"></div>
</div>
END_OF_STAR;

        return $html;
    }

    public function formatPurchaseButton( $targetUrl, $errorMessage = null )
    {
        $purchaseButtonUrl = plugins_url( 'images/available_on_the_app_store.png', dirname(__DIR__) );
        $html = '<div class="eia_purchase_button">';
        $html .= '<a href="' . $targetUrl . '"';
        if ( !empty( $errorMessage ) ) {
            $html .= ' alt="' . $errorMessage . '"';
            $html .= ' title="' . $errorMessage . '"';
        }
        $html .= '>';
        $html .= '<img src="' . $purchaseButtonUrl . '"';
        $html .= ' width="160" height="61"';
        $html .= ' />';
        $html .= '</a></div>';

        return $html;
    }

}

/**
 * Exception class of this plugin
 *
 */
class Rsj_EmbedIphoneIpadAppException extends Exception
{
    public function __construct( $message, $code = 0, Exception $previous = null )
    {
        parent::__construct( $message, $code, $previous );
    }

}
